package compiler.parser.lr;


/// <summary>
import compiler.grammar.Production;
import compiler.grammar.Symbol;

/// Summary description for LRItem.
/// </summary>
public class LRItem
{
    //~ Instance fields --------------------------------------------------------

    private final Production production;
    private int              dotPosition;

    //~ Constructors -----------------------------------------------------------

    public LRItem(Production prod, int dot) throws Exception
    {
        this.production  = prod;
        this.dotPosition = dot;

        if (dot > production.getBody().size())
        {
            throw new Exception("Dot after production");
        }

        if (dot < 0)
        {
            throw new Exception("Dot before zero");
        }
    }

    //~ Methods ----------------------------------------------------------------

    // compares the production and the dot
    @Override
    public boolean equals(Object obj)
    {
        if ((obj == null) || (getClass() != obj.getClass()))
        {
            return false;
        }

        LRItem itm = (LRItem)obj;

        return production.equals(itm.production) && (dotPosition == itm.dotPosition);
    }

    public int getDotPosition()
    {
        return dotPosition;
    }

    public Production getProduction()
    {
        return production;
    }

    public Symbol getSymbolAfterDot()
    {
        // dotPosition is zero-based
        if (dotPosition >= production.getBody().size())
            return null;
        else

            return production.getBody().get(dotPosition); // the dot is just before the symbol with the same index
    }

    public Object getSymbolBeforeDot()
    {
        // dotPosition is zero-based
        if (dotPosition < 1)
            return null;
        else

            return production.getBody().get(dotPosition - 1); // the dot is just before the symbol with the same index
    }

    @Override
    public int hashCode()
    {
        return (50 * production.hashCode()) + dotPosition; // Assuming max getBody()
                                                           // is 50 ( max val
                                                           // for dot is 50 )
    }

    public boolean isDotAtEnd()
    {
        return (dotPosition == production.getBody().size());
    }

    public void setDotPosition(int dotPosition)
    {
        this.dotPosition = dotPosition;
    }
}
